/*
 * Funambol is a mobile platform developed by Funambol, Inc. 
 * Copyright (C) 2008 Funambol, Inc.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission 
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE 
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU Affero General Public License 
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 * 
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite 
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 * 
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 * 
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably 
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */

#include "Event.h"
#include "EventDataStore.h"


#define TABLE_EVENT                     "EVENT"
#define TABLE_RECURRENCE                "RECURRENCE"
#define QUERY_MAX_ID_FROM_EVENT         "SELECT MAX(ROWID) from Event;"
#define QUERY_MAX_ID_FROM_RECURRENCE    "SELECT MAX(ROWID) from Recurrence;"

/**
* Creates a StringBuffer that is the format that must be used 
* inside the Event table
*/
StringBuffer EventDataStore::getDate(Date& d) {
    StringBuffer ret(d.getDate());
    return ret;
}

/**
* Creates a StringBuffer that is the format that must be used 
* inside the Event table. The name can be retieved using the info
* stored inside the Timezone object
*/
StringBuffer EventDataStore::getTimezoneName(Timezone& tz) {    
    StringBuffer tzname(tz.getName());
    return tzname;
}

StringBuffer EventDataStore::getBooleanValue(bool val) {    
    return val == true ? "1" : "0";
}

StringBuffer EventDataStore::createInsertEventStmt(Event& event) {    
     
    StringBuffer query("INSERT INTO ");
    query.append(TABLE_EVENT);
    query.append(" (");    
    // list of fields
    query.append("summary, location, description,");
    query.append("start_date, start_tz, end_date,");
    query.append("all_day, calendar_id, orig_event_id, orig_start_date");
        
    // list of values
    query.append(") values (");    
    
    query.append("'").append(event.getSubject()).append("'").append(",");
    query.append("'").append(event.getLocation()).append("'").append(",");
    query.append("'").append(event.getBody()).append("'").append(",");
            
    query.append(getDate(event.getStart())).append(",");
    query.append("'").append(getTimezoneName(event.getEventTimezone())).append("'").append(",");
    query.append(getDate(event.getEnd())).append(",");
        
    query.append(getBooleanValue(event.getAllDayEvent())).append(",");    
    query.append(event.getCalendar()).append(",");
    query.append(event.getorig_event_id()).append(",");
    query.append(event.getorig_start_date());
          
    query.append(");");
    
    return query;          
}


StringBuffer EventDataStore::createUpdateEventStmt(const char* identifier, Event& event) {    
     
    StringBuffer query("UPDATE ");
    query.append(TABLE_EVENT);
    query.append(" set ");    
    // list of fields
    query.append("summary = "); 
    query.append("'").append(event.getSubject()).append("'").append(",");
    
    query.append("location = "); 
    query.append("'").append(event.getLocation()).append("'").append(",");
    
    query.append("description = "); 
    query.append("'").append(event.getBody()).append("'").append(",");
    
    query.append("start_date = "); 
    query.append(getDate(event.getStart())).append(",");
    
    query.append("start_tz = "); 
    query.append("'").append(getTimezoneName(event.getEventTimezone())).append("'").append(",");
    
    query.append("end_date = "); 
    query.append(getDate(event.getEnd())).append(",");
    
    query.append("all_day = "); 
    query.append(getBooleanValue(event.getAllDayEvent())).append(",");  
    
    query.append("calendar_id = "); 
    query.append(event.getCalendar()).append(","); 
    
    query.append("orig_event_id = "); 
    query.append(event.getorig_event_id()).append(",");
    
    query.append("orig_start_date = "); 
    query.append(event.getorig_start_date());
      
    query.append(" where ROWID = ");
    query.append(identifier);    
    query.append(";");    
    
    return query;          
}


StringBuffer EventDataStore::createDeleteEventStmt(const char* id) {
    StringBuffer query("DELETE FROM ");
    query.append(TABLE_EVENT);
    query.append(" WHERE ROWID = ");
    query.append(id);
    query.append(";");
    return query;
}
    
    
StringBuffer EventDataStore::createUpdateFunEventStateStmt(const char* id) {
    
    StringBuffer query("Update fun_event_state ");
    query.append("set updated_from_client = 1 ");
    query.append("where event_id = ");
    query.append(id);
    query.append(";");
    return query;

}
    
int EventDataStore::addPIMItem(StringBuffer& identifier, const PIMItem& item){

    int ret = 0;    
    Event& event = (Event&)item;
    ArrayList al;
        
    StringBuffer query = createInsertEventStmt(event);
    
    ret = driver.execute(query);
    
    if (ret != 0){
        //LOG.error("EventDataStore.addPIMItem: the item %s can not be inserted: err = %i", event.getSubject(), ret);
        printf("result of execute query: %i", ret);
        goto finally;
        
    }
    ret = driver.commit();
    if (ret != 0){
        //LOG.error("EventDataStore.addPIMItem: error commit: err = %i", ret);                
        goto finally;
    }

    ret = driver.queryIndex(QUERY_MAX_ID_FROM_EVENT, al);
    if (ret != 0){
        //LOG.error("EventDataStore.addPIMItem: error queryIndex: err = %i", ret);                
        goto finally;        
    }
    identifier = ((StringBuffer*)(al.get(0)))->c_str();
    
    query = createUpdateFunEventStateStmt(identifier);
    ret = driver.execute(query);    
    if (ret != 0){
        //LOG.error("EventDataStore.addPIMItem: error createUpdateFunEventStateStmt: err = %i", ret);                
        goto finally;
    }
    
    ret = driver.commit();
    if (ret != 0){
        //LOG.error("EventDataStore.addPIMItem: error commit after fun_event_state: err = %i", ret);                
        goto finally;
    }
    
    // @todo: handle the Recurrence Object if any...
finally:
       
    return ret;
}

int EventDataStore::deletePIMItem(const char* identifier) {

    int ret = 0;

    StringBuffer query = createDeleteEventStmt(identifier);
   
    ret = driver.execute(query);
    if (ret != 0){
         //LOG.error("EventDataStore.deletePIMItem: error queryIndex: err = %i", ret);                
        goto finally;            
    }
    ret = driver.commit();
    
    query = createUpdateFunEventStateStmt(identifier);
    ret = driver.execute(query);    
    if (ret != 0){
        //LOG.error("EventDataStore.deletePIMItem: error createUpdateFunEventStateStmt: err = %i", ret);                
        goto finally;
    }
    
    ret = driver.commit();
    if (ret != 0){
        //LOG.error("EventDataStore.deletePIMItem: error commit after fun_event_state: err = %i", ret);                
        goto finally;
    }
    
    
finally:    
    return ret;
}

int EventDataStore::updatePIMItem(const char* identifier, const PIMItem& item) {
    
    int ret = 0;    
    Event& event = (Event&)item;
    ArrayList al;
        
    StringBuffer query = createUpdateEventStmt(identifier, event);
    
    ret = driver.execute(query);
    
    if (ret != 0){
        //LOG.error("EventDataStore.updatePIMItem: the item %s can not be updated: err = %i", event.getSubject(), ret);
        printf("result of execute query: %i", ret);
        goto finally;
        
    }
    ret = driver.commit();
    if (ret != 0){
        //LOG.error("EventDataStore.updatePIMItem: error commit: err = %i", ret);                
        goto finally;
    }        
    
    query = createUpdateFunEventStateStmt(identifier);
    ret = driver.execute(query);    
    if (ret != 0){
        //LOG.error("EventDataStore.updatePIMItem: error createUpdateFunEventStateStmt: err = %i", ret);                
        goto finally;
    }
    
    ret = driver.commit();
    if (ret != 0){
        //LOG.error("EventDataStore.updatePIMItem: error commit after fun_event_state: err = %i", ret);                
        goto finally;
    }
    
    // @todo: handle the Recurrence Object if any...
finally:
       
    return ret;
}

PIMItem* EventDataStore::getPIMItem(const char* identifier){ 
    
    return 0; 
}
